package com.mew.chess.core.game.pokdeng.game;

import cn.hutool.core.util.RandomUtil;
import com.mew.chess.core.common.handler.ChessPushMessageUtil;
import com.mew.chess.core.common.utils.ChessGameUtil;
import com.mew.chess.core.game.pokdeng.game.common.PokDengConstantValue;
import com.mew.chess.core.game.pokdeng.game.common.PokDengLinkType;
import com.mew.chess.core.game.pokdeng.game.common.PokDengPushCMDMapType;
import com.mew.chess.core.game.pokdeng.game.message.*;
import com.mew.common.enm.UserType;
import com.mew.common.rest.bo.GameSession;
import lombok.Data;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Semaphore;
import java.util.stream.Collectors;

/**
 * @author dylin
 * @create 2021/4/28
 */
@Data
public class PokDengTableManager {
    private final Semaphore semaphore = new Semaphore(1);
    private long ino;//局号

    private int tableId;
    private int minGoldNumber;
    private String betStrs;
    private int[] betArrays;
    private int overTime;
    private long[] maxBetLimit;

    private boolean isControl;//是否控制

    private PokDengScheduleManager scheduleManager;
    private List<Integer> cardLib=new ArrayList<>();

    private final ConcurrentMap<Long, GameSession> onlineUser = new ConcurrentHashMap<>(10);//真人玩家session
    private final ConcurrentMap<Integer,PokDengSeatManager> seatMap = new ConcurrentHashMap<>(10);//在线玩家
    private PokDengSeatManager banker;

    private int askStartSeat;//要牌开始位置
    private int askNowSeat;//要牌当前位置

    private PushStartBetMessage pushStartBetMessage=new PushStartBetMessage();
    private PushDealCardMessage pushDealCardMessage=new PushDealCardMessage();
    private PushAskCardMessage pushAskCardMessage=new PushAskCardMessage();
    private PushMiCardMessage pushMiCardMessage=new PushMiCardMessage();
    private PushOpenCardMessage pushOpenCardMessage=new PushOpenCardMessage();
    private PushBetMessage pushBetMessage=new PushBetMessage();
    private PushUserEEMessage pushUserEEMessage=new PushUserEEMessage();
    private PushKickUserMessage pushKickUserMessage=new PushKickUserMessage();

    //阶段信息
    private int linkType;
    private long startTime;
    private int ruleTime;

    private PokDengTableManager(){}
    public PokDengTableManager(int tableId){
        this.setIno(ChessGameUtil.generateINO(tableId,0));
        this.tableId=tableId;
        for (int i = 0; i < PokDengConstantValue.MAX_SEAT; i++) {
            seatMap.put(i+1,PokDengSeatManager.builder().seatNo(i+1).build());
        }
    }
    public PokDengSeatManager getPokDengSeatManager(Integer id){
        return seatMap.get(id);
    }

    public void registerOnlineUser(GameSession session){
        onlineUser.put(session.getUserId(), session);
    }

    public List<Integer> getEmptySeat(){
        List<Integer> emptySeatList=new ArrayList<>();
        seatMap.values().stream().forEach(s->{
            if(s.getUser()==null){
                emptySeatList.add(s.getSeatNo());
            }
        });
        return emptySeatList;
    }

    /**
     * 检查游戏是否启动
     * @return
     */
    public boolean checkIsNoStart() {
        return scheduleManager.getFlag().get();
    }

    /**
     * 启动游戏
     */
    public void startGame(){
        scheduleManager.start();
    }
    /**
     * 停止游戏
     */
    public void stopGame(){
        scheduleManager.stop();
        this.linkType = PokDengLinkType.Prepare.code();
        this.ruleTime = PokDengConstantValue.PAYMENT_TIME;
        this.startTime = 0;
        for (PokDengSeatManager value : this.seatMap.values()) {
            value.setUser(null);
        }
    }

    /**
     * 进入游戏
     */
    public void pushUserEE(PokDengSeatManager seat,PokDengPushCMDMapType cmd){
        PushUserEEMessage message = this.getPushUserEEMessage();
        message.setSeat(seat);
        List<GameSession> sessionList = this.getOnlineUser().values().stream().filter(u -> u.getUserId() != seat.getUser().getUserId()).collect(Collectors.toList());
        ChessPushMessageUtil.broadcastMessage(sessionList,cmd.code(),message);
    }

    /**
     * 退出游戏
     * @param userId
     */
    public void exitRoom(long userId){
        onlineUser.remove(userId);
        PokDengSeatManager seat = getPlayerSeat(userId);
        if(seat.getUser()!=null&&seat.getUser().getBet()==0){
            clearOnlineUser(userId);
        }
    }

    /**
     * 跳过压注阶段
     */
    public void skipBetLink(){
        for (PokDengSeatManager seat : this.seatMap.values()) {
            if(seat.getUser()!=null&&seat.getUser().getBet()==0){
                return;
            }
        }
        scheduleManager.skipBet();
    }
    /**
     * 阶段改变
     * @param linkType
     * @param ruleTime
     */
    public void changeLink(int linkType,int ruleTime){
        this.linkType=linkType;
        this.startTime=System.currentTimeMillis();
        this.ruleTime=ruleTime;
    }

    /**
     * 清除在线玩家
     * @param userId
     */
    public void clearOnlineUser(Long userId){
        onlineUser.remove(userId);
        seatMap.values().stream().forEach(v->{
            if(null!=v.getUser()&&v.getUser().getUserId()==userId){
                this.pushUserEE(v,PokDengPushCMDMapType.UserExitRoom);
                v.setUser(null);
                return;
            }
        });
    }
    /**
     * 获取玩家桌子
     * @param userId
     */
    public PokDengSeatManager getPlayerSeat(Long userId){
        for (PokDengSeatManager seat : seatMap.values()) {
            if(null!=seat.getUser()&&seat.getUser().getUserId()==userId){
                return seat;
            }
        }
        return null;
    }

    /**
     * 剔除不合规的人
     */
    public void kick(){
        for (PokDengSeatManager seat : this.getSeatMap().values()) {
            if(seat.getUser()!=null){
                if(seat.getUser().getUserType()==UserType.Robot.code()){
                    kickRobot(seat.getUser());
                }else{
                    kickPlayer(seat.getUser());
                }
            }
        }
    }

    /**
     * 剔除真人
     * @param user
     */
    private void kickPlayer(UserMessage user){
        if(user.getGoldNumber()<this.getBetArrays()[0]*5){
            ChessPushMessageUtil.pushMessage(this.getOnlineUser().get(user.getUserId()), PokDengPushCMDMapType.KickUser.code(), this.getPushKickUserMessage());
            exitRoom(user.getUserId());
        }
    }
    /**
     * 剔除机器人
     * @param user
     */
    private void kickRobot(UserMessage user){
        if(user.getKickGold()>user.getGoldNumber()||user.getPlayTimes()<=0){
            clearOnlineUser(user.getUserId());
        }
    }
    public void initData(){
        banker.getUser().clear();
        this.setIno(ChessGameUtil.generateINO(this.tableId,this.ino));
        seatMap.values().stream().forEach(v->{
            if(null!=v.getUser()){
                v.getUser().clear();
            }
        });
        cardLib.clear();
        this.askStartSeat=RandomUtil.randomInt(PokDengConstantValue.MAX_SEAT);
        this.askNowSeat=0;
        this.isControl=false;
        kick();
    }
}
